#include "MySqlConPool.h"
#include "../../log.h"
#include "../../ConfigMgr.h"


MySqlPool::MySqlPool() 
{
    auto config = ConfigMgr::GetConfig();
    _poolSize = config->MySqlInfo.PoolSize;
    _port = config->MySqlInfo.Port;
    _host = config->MySqlInfo.IP;
    _pass = config->MySqlInfo.Pwd;
    _user = config->MySqlInfo.User;
    _db = config->MySqlInfo.DB;
    
    for (int i = 0; i < _poolSize; ++i) 
    {
        MYSQL* conn = createConnection();
        if (conn) 
        {
            _pool.push(conn);
        } 
        else 
        {
            log_error("Failed to create MySQL connection: {}", mysql_error(conn) ? mysql_error(conn) : "Unknown error");
        }
    }
}

// 获取一个RAII封装的连接
MySqlPool::ConnectionGuard MySqlPool::acquire() 
{
    MYSQL* conn = getConnection();
    return ConnectionGuard(*this, conn);
}

void MySqlPool::close() 
{
    std::unique_lock<std::mutex> lock(_mutex);
    _stop = true;
    _cond.notify_all();
    while (!_pool.empty()) 
    {
        MYSQL* conn = _pool.front();
        mysql_close(conn);
        _pool.pop();
    }
}

void MySqlPool::show()
{
    log_info("mysql pool size: {}", _poolSize);
    log_info("mysql host: {}", _host);
    log_info("mysql port: {}", _port);
    log_info("mysql user: {}", _user);
    log_info("mysql db: {}", _db);
}


MYSQL* MySqlPool::createConnection() 
{
    MYSQL* conn = mysql_init(nullptr);
    if (!conn) return nullptr;

    if (!mysql_real_connect(conn, _host.c_str(), _user.c_str(),
                            _pass.c_str(), _db.c_str(),
                            _port, nullptr, 0)) 
    {
        log_error("MySQL connect error: {}", mysql_error(conn));
        mysql_close(conn);
        return nullptr;
    }
    mysql_set_character_set(conn, "utf8mb4");
    return conn;
}

MYSQL* MySqlPool::getConnection() 
{
    std::unique_lock<std::mutex> lock(_mutex);
    _cond.wait(lock, [this] {
        return _stop || !_pool.empty();
    });

    if (_stop) return nullptr;

    MYSQL* conn = _pool.front();
    _pool.pop();

    // 检查连接是否存活
    if (mysql_ping(conn) != 0) 
    {
        mysql_close(conn);
        conn = createConnection();
    }
    return conn;
}

void MySqlPool::returnConnection(MYSQL* conn) 
{
    std::unique_lock<std::mutex> lock(_mutex);
    if (_stop || conn == nullptr) 
    {
        if (conn) mysql_close(conn);
        return;
    }
    _pool.push(conn);
    _cond.notify_one();
}